"""
text_editor.py

提供类似PS的文本框功能，允许在图像上添加可调整大小和颜色的文本。
"""

import matplotlib
import os
import sys
import warnings
import glob

# 忽略字体警告
warnings.filterwarnings("ignore", category=UserWarning, module="matplotlib")

# 设置字体路径 - 确保使用绝对路径
current_dir = os.path.dirname(os.path.abspath(__file__))
fonts_dir = os.path.join(current_dir, 'fonts')
kaiti_path = os.path.join(fonts_dir, 'kaiti.TTF')

# 添加字体文件
from matplotlib.font_manager import FontProperties, fontManager

# 存储字体信息的字典，键为字体名称，值为字体路径
font_dict = {}

# 加载fonts文件夹中的所有字体
def load_custom_fonts():
    """加载fonts文件夹中的所有字体"""
    if os.path.exists(fonts_dir):
        print(f"正在从 {fonts_dir} 加载字体...")
        font_files = glob.glob(os.path.join(fonts_dir, '*.ttf')) + glob.glob(os.path.join(fonts_dir, '*.TTF')) + glob.glob(os.path.join(fonts_dir, '*.ttc')) + glob.glob(os.path.join(fonts_dir, '*.TTC'))
        if not font_files:
            print(f"警告: 在 {fonts_dir} 中没有找到字体文件")
        for font_file in font_files:
            try:
                # 获取字体文件名（不含扩展名）
                font_name = os.path.splitext(os.path.basename(font_file))[0]
                # 添加字体到字体管理器
                fontManager.addfont(font_file)
                # 创建字体属性对象
                font_prop = FontProperties(fname=font_file)
                # 存储字体信息
                font_dict[font_name] = {
                    'path': font_file,
                    'prop': font_prop
                }
                print(f"成功加载字体: {font_name} - {font_file}")
            except Exception as e:
                print(f"加载字体失败 {font_file}: {e}")
    else:
        print(f"字体文件夹不存在: {fonts_dir}")
        # 尝试创建fonts文件夹
        try:
            os.makedirs(fonts_dir)
            print(f"已创建字体文件夹: {fonts_dir}")
        except Exception as e:
            print(f"创建字体文件夹失败: {e}")

# 加载自定义字体
load_custom_fonts()

# 确保楷体字体存在
if os.path.exists(kaiti_path):
    try:
        if 'kaiti' not in font_dict:
            fontManager.addfont(kaiti_path)
            kaiti_font = FontProperties(fname=kaiti_path)
            font_dict['kaiti'] = {
                'path': kaiti_path,
                'prop': kaiti_font
            }
        else:
            kaiti_font = font_dict['kaiti']['prop']
        print(f"成功加载楷体字体: {kaiti_path}")
    except Exception as e:
        print(f"加载楷体字体失败: {e}")
        # 创建一个默认字体属性
        kaiti_font = FontProperties(family="sans-serif")
else:
    print(f"楷体字体文件不存在: {kaiti_path}")
    # 创建一个默认字体属性
    kaiti_font = FontProperties(family="sans-serif")
    # 如果字典中有其他字体，使用第一个可用的字体
    if font_dict:
        first_font_name = next(iter(font_dict))
        kaiti_font = font_dict[first_font_name]['prop']
        print(f"使用替代字体: {first_font_name}")

# 注册系统中的所有字体
def register_system_fonts():
    """注册系统中的所有字体"""
    try:
        # Windows系统字体目录
        if sys.platform == 'win32':
            font_dirs = [
                os.path.join(os.environ['WINDIR'], 'Fonts'),
                os.path.join(os.environ['LOCALAPPDATA'], 'Microsoft', 'Windows', 'Fonts')
            ]
            for font_dir in font_dirs:
                if os.path.exists(font_dir):
                    for font_file in os.listdir(font_dir):
                        if font_file.lower().endswith(('.ttf', '.ttc', '.otf')):
                            try:
                                font_path = os.path.join(font_dir, font_file)
                                fontManager.addfont(font_path)
                            except:
                                pass
        # macOS系统字体目录
        elif sys.platform == 'darwin':
            font_dirs = [
                '/Library/Fonts',
                '/System/Library/Fonts',
                os.path.expanduser('~/Library/Fonts')
            ]
            for font_dir in font_dirs:
                if os.path.exists(font_dir):
                    for font_file in os.listdir(font_dir):
                        if font_file.lower().endswith(('.ttf', '.ttc', '.otf')):
                            try:
                                font_path = os.path.join(font_dir, font_file)
                                fontManager.addfont(font_path)
                            except:
                                pass
        # Linux系统字体目录
        elif sys.platform.startswith('linux'):
            font_dirs = [
                '/usr/share/fonts',
                '/usr/local/share/fonts',
                os.path.expanduser('~/.fonts')
            ]
            for font_dir in font_dirs:
                if os.path.exists(font_dir):
                    for root, dirs, files in os.walk(font_dir):
                        for font_file in files:
                            if font_file.lower().endswith(('.ttf', '.ttc', '.otf')):
                                try:
                                    font_path = os.path.join(root, font_file)
                                    fontManager.addfont(font_path)
                                except:
                                    pass
    except Exception as e:
        print(f"注册系统字体时出错: {e}")

# 尝试注册系统字体
register_system_fonts()

# 设置默认字体
matplotlib.rcParams['font.sans-serif'] = ['KaiTi', 'SimHei', 'SimSun', 'Microsoft YaHei', 'DejaVu Sans']
matplotlib.rcParams['axes.unicode_minus'] = False

from PyQt5.QtWidgets import (
    QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
    QPushButton, QColorDialog, QSpinBox, QComboBox, QFontComboBox,
    QGroupBox, QMessageBox, QTableWidgetItem
)
from PyQt5.QtGui import QColor, QFont
from PyQt5.QtCore import Qt

class TextEditorDialog(QDialog):
    """
    文本编辑对话框，用于输入文本内容并设置文本样式
    """
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("添加文本")
        self.resize(400, 300)
        
        # 初始化默认值
        self.text_content = ""
        self.text_color = QColor(0, 0, 0)  # 默认黑色
        self.font_size = 12
        self.font_family = "kaiti"  # 默认使用楷体
        self.font_weight = "normal"
        self.font_style = "normal"
        
        self.setup_ui()
        
    def setup_ui(self):
        """设置UI界面"""
        layout = QVBoxLayout()
        
        # 文本内容输入
        content_group = QGroupBox("文本内容")
        content_layout = QVBoxLayout()
        self.text_edit = QLineEdit()
        self.text_edit.setPlaceholderText("请输入文本内容...")
        content_layout.addWidget(self.text_edit)
        content_group.setLayout(content_layout)
        layout.addWidget(content_group)
        
        # 字体设置
        font_group = QGroupBox("字体设置")
        font_layout = QVBoxLayout()
        
        # 字体选择
        font_family_layout = QHBoxLayout()
        font_family_layout.addWidget(QLabel("字体:"))
        
        # 使用自定义下拉列表代替QFontComboBox
        self.font_combo = QComboBox()
        
        # 添加fonts文件夹中的字体
        if font_dict:
            for font_name in sorted(font_dict.keys()):
                self.font_combo.addItem(font_name)
            
            # 设置默认字体为楷体
            default_index = self.font_combo.findText("kaiti")
            if default_index >= 0:
                self.font_combo.setCurrentIndex(default_index)
            else:
                # 如果没有找到楷体，使用第一个字体
                self.font_combo.setCurrentIndex(0)
        else:
            # 如果没有找到任何字体，添加一个默认选项
            self.font_combo.addItem("默认字体")
        
        font_family_layout.addWidget(self.font_combo)
        font_layout.addLayout(font_family_layout)
        
        # 字体大小
        font_size_layout = QHBoxLayout()
        font_size_layout.addWidget(QLabel("大小:"))
        self.size_spin = QSpinBox()
        self.size_spin.setRange(6, 72)
        self.size_spin.setValue(self.font_size)
        font_size_layout.addWidget(self.size_spin)
        font_layout.addLayout(font_size_layout)
        
        # 字体样式
        style_layout = QHBoxLayout()
        
        # 粗体选择
        style_layout.addWidget(QLabel("粗细:"))
        self.weight_combo = QComboBox()
        self.weight_combo.addItems(["正常", "粗体"])
        style_layout.addWidget(self.weight_combo)
        
        # 斜体选择
        style_layout.addWidget(QLabel("样式:"))
        self.style_combo = QComboBox()
        self.style_combo.addItems(["正常", "斜体"])
        style_layout.addWidget(self.style_combo)
        
        font_layout.addLayout(style_layout)
        
        # 颜色选择
        color_layout = QHBoxLayout()
        color_layout.addWidget(QLabel("颜色:"))
        self.color_btn = QPushButton()
        self.color_btn.setFixedSize(80, 20)
        self.update_color_button()
        self.color_btn.clicked.connect(self.choose_color)
        color_layout.addWidget(self.color_btn)
        font_layout.addLayout(color_layout)
        
        font_group.setLayout(font_layout)
        layout.addWidget(font_group)
        
        # 确定和取消按钮
        btn_layout = QHBoxLayout()
        self.btn_ok = QPushButton("确定")
        self.btn_ok.clicked.connect(self.accept)
        self.btn_cancel = QPushButton("取消")
        self.btn_cancel.clicked.connect(self.reject)
        
        btn_layout.addWidget(self.btn_ok)
        btn_layout.addWidget(self.btn_cancel)
        layout.addLayout(btn_layout)
        
        self.setLayout(layout)
    
    def update_color_button(self):
        """更新颜色按钮的背景色"""
        self.color_btn.setStyleSheet(
            f"background-color: rgb({self.text_color.red()}, {self.text_color.green()}, {self.text_color.blue()}); "
            f"border: 1px solid #888888;"
        )
    
    def choose_color(self):
        """打开颜色选择对话框"""
        color = QColorDialog.getColor(self.text_color, self, "选择文本颜色")
        if color.isValid():
            self.text_color = color
            self.update_color_button()
    
    def get_text_data(self):
        """
        获取文本数据
        
        :return: 文本数据字典
        """
        text = self.text_edit.text().strip()
        
        # 获取字体信息
        if self.font_combo.count() > 0:
            font_family = self.font_combo.currentText()
        else:
            font_family = "默认字体"
            
        font_size = self.size_spin.value()
        font_weight = 'bold' if self.weight_combo.currentText() == "粗体" else 'normal'
        font_style = 'italic' if self.style_combo.currentText() == "斜体" else 'normal'
        
        # 获取颜色
        color = self.text_color
        r, g, b = color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0
        
        return {
            "text": text,
            "font_family": font_family,
            "font_size": font_size,
            "font_weight": font_weight,
            "font_style": font_style,
            "color": (r, g, b, 1.0)
        }
    
    def validate(self):
        """验证输入是否有效"""
        if not self.text_edit.text().strip():
            QMessageBox.warning(self, "警告", "文本内容不能为空！")
            return False
        return True
    
    def accept(self):
        """确认按钮点击事件"""
        if self.validate():
            super().accept()


class TextEditor:
    """
    文本编辑器类，负责管理文本的添加、编辑和删除
    """
    def __init__(self, canvas, table_widget):
        """
        初始化文本编辑器
        
        :param canvas: ImageCanvas对象
        :param table_widget: QTableWidget显示文本列表
        """
        self.canvas = canvas
        self.ax = self.canvas.ax
        self.table_widget = table_widget
        
        # 存储文本对象列表
        self.text_objects = []
        self.is_text_editing = False
        self.current_text_data = None
        
        # 设置表格列
        self.table_widget.setColumnCount(3)
        self.table_widget.setHorizontalHeaderLabels(["文本内容", "字体大小", "颜色"])
    
    def start_text_editing(self):
        """进入文本编辑模式"""
        self.is_text_editing = True
        self.canvas.enable_pan = False
    
    def stop_text_editing(self):
        """退出文本编辑模式"""
        self.is_text_editing = False
        self.canvas.enable_pan = True
    
    def add_text(self, x, y, text_data):
        """
        在图像上添加文本
        
        :param x: x坐标
        :param y: y坐标
        :param text_data: 文本数据字典
        """
        try:
            if not text_data["text"]:
                raise ValueError("文本内容不能为空")
            
            # 使用选择的字体
            font_name = text_data["font_family"]
            if font_name in font_dict:
                font_prop = font_dict[font_name]["prop"]
            elif font_dict:
                # 如果找不到选择的字体，但有其他字体可用，使用第一个可用的字体
                first_font_name = next(iter(font_dict))
                font_prop = font_dict[first_font_name]["prop"]
                print(f"找不到字体 '{font_name}'，使用替代字体: {first_font_name}")
            else:
                # 如果没有任何字体可用，使用默认字体
                font_prop = FontProperties(family="sans-serif")
                print("没有可用的字体，使用系统默认字体")
                
            # 创建文本对象
            text_obj = self.ax.text(
                x, y,
                text_data["text"],
                fontsize=text_data["font_size"],
                fontproperties=font_prop,
                fontweight=text_data["font_weight"],
                fontstyle=text_data["font_style"],
                color=text_data["color"],
                transform=self.ax.transData,
                ha='left',
                va='top'
            )
            
            # 存储文本对象信息
            text_item = {
                'x': x, 
                'y': y, 
                'text_data': text_data,
                'text_obj': text_obj
            }
            self.text_objects.append(text_item)
            
            # 更新表格
            row_index = self.table_widget.rowCount()
            self.table_widget.insertRow(row_index)
            self.table_widget.setItem(row_index, 0, QTableWidgetItem(text_data["text"]))
            self.table_widget.setItem(row_index, 1, QTableWidgetItem(str(text_data["font_size"])))
            
            # 颜色显示
            color_text = f"R:{int(text_data['color'][0]*255)},G:{int(text_data['color'][1]*255)},B:{int(text_data['color'][2]*255)}"
            self.table_widget.setItem(row_index, 2, QTableWidgetItem(color_text))
            
            # 重绘画布
            self.canvas.draw()
            
        except Exception as e:
            QMessageBox.critical(None, "添加文本错误", f"添加文本时发生错误：{str(e)}")
    
    def clear_texts(self):
        """清除所有文本和表格内容"""
        for text_item in self.text_objects:
            try:
                if 'text_obj' in text_item and text_item['text_obj'] is not None:
                    text_item['text_obj'].remove()
            except Exception:
                # 如果移除失败，忽略错误
                pass
        
        self.text_objects.clear()
        self.table_widget.setRowCount(0)
        self.canvas.draw()
    
    def remove_text(self, index):
        """
        删除指定索引的文本
        
        :param index: 文本索引
        """
        if 0 <= index < len(self.text_objects):
            try:
                # 移除文本对象
                text_item = self.text_objects[index]
                if 'text_obj' in text_item and text_item['text_obj'] is not None:
                    text_item['text_obj'].remove()
                
                # 从列表中删除
                self.text_objects.pop(index)
                
                # 从表格中删除
                self.table_widget.removeRow(index)
                
                # 重绘画布
                self.canvas.draw()
                
            except Exception as e:
                QMessageBox.critical(None, "删除文本错误", f"删除文本时发生错误：{str(e)}") 